// --------------------------------------------------------------------------------------------------------------------

// <copyright file="CollectionAssert.cs" company="Social Development Spb">

//   Copyright (c) Social Development Spb 2009

// </copyright>

// <summary>

//   Defines collections assertion methods.

// </summary>

// --------------------------------------------------------------------------------------------------------------------


using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;

namespace Diagnostics
{
    #region Imported Namespaces

    

    #endregion


    /// <summary>
    /// Defines collections assertion methods.
    /// </summary>
    public static class CollectionAssert
    {
        #region Constants and Fields

        private const string _collectionIsEmptyMessage = "Collection is empty.";
        private const string _collectionIsNotEmptyMessage = "Collection is not empty.";

        private const string _specifiedKeyValuePairWasAlreadyAddedMessage =
            "A specified key-valuePair was already added to a dictionary.";

        private const string _specifiedKeyWasAlreadyAddedMessage = "A specified key was already added to a dictionary.";

        #endregion


        #region Public Methods

        /// <summary>
        /// Asserts that a specified <see cref="ICollection{T}"/> contains a specified item.
        /// </summary>
        /// <typeparam name="T">
        /// The type of collection items.
        /// </typeparam>
        /// <param name="collection">
        /// A <see cref="ICollection{T}"/> to check.
        /// </param>
        /// <param name="item">
        /// An item to check.
        /// </param>
        /// <param name="name">
        /// A name of collection items.
        /// </param>
        [Conditional("DEBUG")]
        public static void Contains<T>(ICollection<T> collection, T item, string name)
        {
            Debug.Assert(
                collection.Contains(item), string.Format(CultureInfo.CurrentCulture, "A specified {0} was not found.", name));
        }


        /// <summary>
        /// Asserts that a specified <see cref="ICollection{T}"/> contains a specified item.
        /// </summary>
        /// <typeparam name="T">
        /// The type of collection items.
        /// </typeparam>
        /// <param name="collection">
        /// A <see cref="ICollection{T}"/> to check.
        /// </param>
        /// <param name="item">
        /// An item to check.
        /// </param>
        [Conditional("DEBUG")]
        public static void Contains<T>(ICollection<T> collection, T item)
        {
            Debug.Assert(
                collection.Contains(item), 
                string.Format(CultureInfo.CurrentCulture, "A specified {0} was not found.", typeof(T).Name));
        }


        /// <summary>
        /// Asserts that a specified <see cref="ICollection{T}"/> contains a specified item.
        /// </summary>
        /// <typeparam name="T">
        /// The type of collection items.
        /// </typeparam>
        /// <param name="collection">
        /// A <see cref="ICollection{T}"/> to check.
        /// </param>
        /// <param name="item">
        /// An item to check.
        /// </param>
        /// <param name="messageFormat">
        /// A composite format string.
        /// </param>
        /// <param name="arguments">
        /// An array of objects to format.
        /// </param>
        [Conditional("DEBUG")]
        public static void Contains<T>(ICollection<T> collection, T item, string messageFormat, params object[] arguments)
            where T : class
        {
            Debug.Assert(collection.Contains(item), string.Format(CultureInfo.CurrentCulture, messageFormat, arguments));
        }


        /// <summary>
        /// Asserts that a specified <see cref="IDictionary{TKey, TValue}"/> contains a specified key.
        /// </summary>
        /// <typeparam name="TKey">
        /// The type of the key.
        /// </typeparam>
        /// <typeparam name="TValue">
        /// The type of the value.
        /// </typeparam>
        /// <param name="dictionary">
        /// A <see cref="IDictionary{TKey, TValue}"/> to check.
        /// </param>
        /// <param name="key">
        /// A key to check.
        /// </param>
        [Conditional("DEBUG")]
        public static void ContainsKey<TKey, TValue>(IDictionary<TKey, TValue> dictionary, TKey key)
        {
            Debug.Assert(dictionary.ContainsKey(key), _specifiedKeyWasAlreadyAddedMessage);
        }


        /// <summary>
        /// Asserts that a specified <see cref="IDictionary{TKey, TValue}"/> contains a specified key.
        /// </summary>
        /// <typeparam name="TKey">
        /// The type of the key.
        /// </typeparam>
        /// <typeparam name="TValue">
        /// The type of the value.
        /// </typeparam>
        /// <param name="dictionary">
        /// A <see cref="IDictionary{TKey, TValue}"/> to check.
        /// </param>
        /// <param name="key">
        /// A key to check.
        /// </param>
        /// <param name="detailMessage">
        /// A <see cref="System.String"/> containing detail message.
        /// </param>
        [Conditional("DEBUG")]
        public static void ContainsKey<TKey, TValue>(IDictionary<TKey, TValue> dictionary, TKey key, string detailMessage)
        {
            Debug.Assert(dictionary.ContainsKey(key), _specifiedKeyWasAlreadyAddedMessage, detailMessage);
        }


        /// <summary>
        /// Asserts that a specified <see cref="IDictionary{TKey, TValue}"/> contains a specified key.
        /// </summary>
        /// <typeparam name="TKey">
        /// The type of the key.
        /// </typeparam>
        /// <typeparam name="TValue">
        /// The type of the value.
        /// </typeparam>
        /// <param name="dictionary">
        /// A <see cref="IDictionary{TKey, TValue}"/> to check.
        /// </param>
        /// <param name="key">
        /// A key to check.
        /// </param>
        /// <param name="detailMessageFormat">
        /// A <see cref="System.String"/> containing composite detail message format.
        /// </param>
        /// <param name="arguments">
        /// An array of objects to format.
        /// </param>
        [Conditional("DEBUG")]
        public static void ContainsKey<TKey, TValue>(
            IDictionary<TKey, TValue> dictionary, TKey key, string detailMessageFormat, params object[] arguments)
        {
            string message = string.Format(CultureInfo.CurrentCulture, detailMessageFormat, arguments);
            Debug.Assert(dictionary.ContainsKey(key), _specifiedKeyWasAlreadyAddedMessage, message);
        }


        /// <summary>
        /// Asserts that the specified collection is empty.
        /// </summary>
        /// <typeparam name="T">
        /// Collection items type.
        /// </typeparam>
        /// <param name="collection">
        /// An instance of a <see cref="System.Collections.Generic.ICollection{T}"/>.
        /// </param>
        [Conditional("DEBUG")]
        public static void IsEmpty<T>(ICollection<T> collection)
        {
            Debug.Assert(collection.Count == 0, _collectionIsNotEmptyMessage);
        }


        /// <summary>
        /// Asserts that the specified collection is empty.
        /// </summary>
        /// <typeparam name="T">
        /// Collection items type.
        /// </typeparam>
        /// <param name="collection">
        /// An instance of a <see cref="System.Collections.Generic.ICollection{T}"/>.
        /// </param>
        /// <param name="message">
        /// A <see cref="System.String"/> message to display.
        /// </param>
        [Conditional("DEBUG")]
        public static void IsEmpty<T>(ICollection<T> collection, string message)
        {
            Debug.Assert(collection.Count == 0, _collectionIsNotEmptyMessage, message);
        }


        /// <summary>
        /// Asserts that the specified collection is not empty.
        /// </summary>
        /// <typeparam name="T">
        /// Collection items type.
        /// </typeparam>
        /// <param name="collection">
        /// An instance of a <see cref="System.Collections.Generic.ICollection{T}"/>.
        /// </param>
        [Conditional("DEBUG")]
        public static void IsNotEmpty<T>(ICollection<T> collection)
        {
            Debug.Assert(collection.Count != 0, _collectionIsEmptyMessage);
        }


        /// <summary>
        /// Asserts that the specified collection is not empty.
        /// </summary>
        /// <typeparam name="T">
        /// Collection items type.
        /// </typeparam>
        /// <param name="collection">
        /// An instance of a <see cref="System.Collections.Generic.ICollection{T}"/>.
        /// </param>
        /// <param name="message">
        /// A <see cref="System.String"/> message to display.
        /// </param>
        [Conditional("DEBUG")]
        public static void IsNotEmpty<T>(ICollection<T> collection, string message)
        {
            Debug.Assert(collection.Count != 0, _collectionIsEmptyMessage, message);
        }


        /// <summary>
        /// Asserts that a specified <see cref="ICollection{T}"/> doesn't contain a specified item.
        /// </summary>
        /// <typeparam name="T">
        /// The type of collection items.
        /// </typeparam>
        /// <param name="collection">
        /// A <see cref="ICollection{T}"/> to check.
        /// </param>
        /// <param name="item">
        /// An item to check.
        /// </param>
        /// <param name="name">
        /// A name of collection items.
        /// </param>
        [Conditional("DEBUG")]
        public static void NotContains<T>(ICollection<T> collection, T item, string name)
        {
            Debug.Assert(
                !collection.Contains(item), 
                string.Format(CultureInfo.CurrentCulture, "A specified {0} was already added.", name));
        }


        /// <summary>
        /// Asserts that a specified <see cref="ICollection{T}"/> doesn't contain a specified item.
        /// </summary>
        /// <typeparam name="T">
        /// The type of collection items.
        /// </typeparam>
        /// <param name="collection">
        /// A <see cref="ICollection{T}"/> to check.
        /// </param>
        /// <param name="item">
        /// An item to check.
        /// </param>
        [Conditional("DEBUG")]
        public static void NotContains<T>(ICollection<T> collection, T item)
        {
            Debug.Assert(
                !collection.Contains(item), 
                string.Format(CultureInfo.CurrentCulture, "A specified {0} was already added.", typeof(T).Name));
        }


        /// <summary>
        /// Asserts that a specified <see cref="ICollection{T}"/> doesn't contain a specified item.
        /// </summary>
        /// <typeparam name="T">
        /// The type of collection items.
        /// </typeparam>
        /// <param name="collection">
        /// A <see cref="ICollection{T}"/> to check.
        /// </param>
        /// <param name="item">
        /// An item to check.
        /// </param>
        /// <param name="messageFormat">
        /// A composite format string.
        /// </param>
        /// <param name="arguments">
        /// An array of objects to format.
        /// </param>
        [Conditional("DEBUG")]
        public static void NotContains<T>(
            ICollection<T> collection, T item, string messageFormat, params object[] arguments)
        {
            Debug.Assert(!collection.Contains(item), string.Format(CultureInfo.CurrentCulture, messageFormat, arguments));
        }


        /// <summary>
        /// Asserts that a specified <see cref="IDictionary{TKey, TValue}"/> doesn't contain a specified key-value pair.
        /// </summary>
        /// <typeparam name="TKey">
        /// The type of the key.
        /// </typeparam>
        /// <typeparam name="TValue">
        /// The type of the value.
        /// </typeparam>
        /// <param name="dictionary">
        /// A <see cref="IDictionary{TKey, TValue}"/> to check.
        /// </param>
        /// <param name="key">
        /// A key to check.
        /// </param>
        /// <param name="value">
        /// A value to check.
        /// </param>
        [Conditional("DEBUG")]
        public static void NotContains<TKey, TValue>(IDictionary<TKey, TValue> dictionary, TKey key, TValue value)
        {
            var keyValuePair = new KeyValuePair<TKey, TValue>(key, value);
            Debug.Assert(!dictionary.Contains(keyValuePair), _specifiedKeyValuePairWasAlreadyAddedMessage);
        }


        /// <summary>
        /// Asserts that a specified <see cref="IDictionary{TKey, TValue}"/> doesn't contain a specified key-value pair.
        /// </summary>
        /// <typeparam name="TKey">
        /// The type of the key.
        /// </typeparam>
        /// <typeparam name="TValue">
        /// The type of the value.
        /// </typeparam>
        /// <param name="dictionary">
        /// A <see cref="IDictionary{TKey, TValue}"/> to check.
        /// </param>
        /// <param name="key">
        /// A key to check.
        /// </param>
        /// <param name="value">
        /// A value to check.
        /// </param>
        /// <param name="detailMessage">
        /// A <see cref="System.String"/> containing detail message.
        /// </param>
        [Conditional("DEBUG")]
        public static void NotContains<TKey, TValue>(
            IDictionary<TKey, TValue> dictionary, TKey key, TValue value, string detailMessage)
        {
            var keyValuePair = new KeyValuePair<TKey, TValue>(key, value);
            Debug.Assert(!dictionary.Contains(keyValuePair), _specifiedKeyValuePairWasAlreadyAddedMessage, detailMessage);
        }


        /// <summary>
        /// Asserts that a specified <see cref="IDictionary{TKey, TValue}"/> doesn't contain a specified key-value pair.
        /// </summary>
        /// <typeparam name="TKey">
        /// The type of the key.
        /// </typeparam>
        /// <typeparam name="TValue">
        /// The type of the value.
        /// </typeparam>
        /// <param name="dictionary">
        /// A <see cref="IDictionary{TKey, TValue}"/> to check.
        /// </param>
        /// <param name="key">
        /// A key to check.
        /// </param>
        /// <param name="value">
        /// A value to check.
        /// </param>
        /// <param name="detailMessageFormat">
        /// A <see cref="System.String"/> containing composite detail message format.
        /// </param>
        /// <param name="arguments">
        /// An array of objects to format.
        /// </param>
        [Conditional("DEBUG")]
        public static void NotContains<TKey, TValue>(
            IDictionary<TKey, TValue> dictionary, 
            TKey key, 
            TValue value, 
            string detailMessageFormat, 
            params object[] arguments)
        {
            var keyValuePair = new KeyValuePair<TKey, TValue>(key, value);
            string message = string.Format(CultureInfo.CurrentCulture, detailMessageFormat, arguments);
            Debug.Assert(!dictionary.Contains(keyValuePair), _specifiedKeyValuePairWasAlreadyAddedMessage, message);
        }


        /// <summary>
        /// Asserts that a specified <see cref="IDictionary{TKey, TValue}"/> doesn't contain a specified key.
        /// </summary>
        /// <typeparam name="TKey">
        /// The type of the key.
        /// </typeparam>
        /// <typeparam name="TValue">
        /// The type of the value.
        /// </typeparam>
        /// <param name="dictionary">
        /// A <see cref="IDictionary{TKey, TValue}"/> to check.
        /// </param>
        /// <param name="key">
        /// A key to check.
        /// </param>
        [Conditional("DEBUG")]
        public static void NotContainsKey<TKey, TValue>(IDictionary<TKey, TValue> dictionary, TKey key)
        {
            Debug.Assert(!dictionary.ContainsKey(key), _specifiedKeyWasAlreadyAddedMessage);
        }


        /// <summary>
        /// Asserts that a specified <see cref="IDictionary{TKey, TValue}"/> doesn't contain a specified key.
        /// </summary>
        /// <typeparam name="TKey">
        /// The type of the key.
        /// </typeparam>
        /// <typeparam name="TValue">
        /// The type of the value.
        /// </typeparam>
        /// <param name="dictionary">
        /// A <see cref="IDictionary{TKey, TValue}"/> to check.
        /// </param>
        /// <param name="key">
        /// A key to check.
        /// </param>
        /// <param name="detailMessage">
        /// A <see cref="System.String"/> containing detail message.
        /// </param>
        [Conditional("DEBUG")]
        public static void NotContainsKey<TKey, TValue>(
            IDictionary<TKey, TValue> dictionary, TKey key, string detailMessage)
        {
            Debug.Assert(!dictionary.ContainsKey(key), _specifiedKeyWasAlreadyAddedMessage, detailMessage);
        }


        /// <summary>
        /// Asserts that a specified <see cref="IDictionary{TKey, TValue}"/> doesn't contain a specified key.
        /// </summary>
        /// <typeparam name="TKey">
        /// The type of the key.
        /// </typeparam>
        /// <typeparam name="TValue">
        /// The type of the value.
        /// </typeparam>
        /// <param name="dictionary">
        /// A <see cref="IDictionary{TKey, TValue}"/> to check.
        /// </param>
        /// <param name="key">
        /// A key to check.
        /// </param>
        /// <param name="detailMessageFormat">
        /// A <see cref="System.String"/> containing composite detail message format.
        /// </param>
        /// <param name="arguments">
        /// An array of objects to format.
        /// </param>
        [Conditional("DEBUG")]
        public static void NotContainsKey<TKey, TValue>(
            IDictionary<TKey, TValue> dictionary, TKey key, string detailMessageFormat, params object[] arguments)
        {
            string message = string.Format(CultureInfo.CurrentCulture, detailMessageFormat, arguments);
            Debug.Assert(!dictionary.ContainsKey(key), _specifiedKeyWasAlreadyAddedMessage, message);
        }

        #endregion
    }
}